package com.atu.poker.service;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.atu.poker.dao.RoomInfoDAO;
import com.atu.poker.dao.RoomSeatDAO;
import com.atu.poker.dao.impl.RoomInfoDAOJdbcImpl;
import com.atu.poker.dao.impl.RoomSeatDAOJdbcImpl;
import com.atu.poker.map.CardMap;
import com.atu.poker.po.Seat;
import com.atu.poker.util.RespUtil;

import server.MainSocket;

public class RoomSeatService {
	private static Logger logger = LogManager.getLogger(RoomSeatService.class);
	private RoomSeatDAO roomSeatDAO = new RoomSeatDAOJdbcImpl();
	private RoomInfoDAO roomInfoDAO = new RoomInfoDAOJdbcImpl();

	/**
	 * 根据seatId获取房间号，用户昵称，座位号
	 * 
	 * @param seatId
	 * @return
	 */
	public Object getSeat(String seatId) {
		Seat seat = roomSeatDAO.getSelfSeat(seatId);
		String roomId = seat.getRoomId();
		long userLimit = Long.parseLong(roomInfoDAO.getUserLimit(roomId));
		long seatNo = Long.parseLong(seat.getSeatNo());
		List<Object> seatList = new ArrayList<>();
		seatList.add(seat);
		List<Seat> otherSeatList = roomSeatDAO.getOtherSeatMap(roomId, seatNo + "");
		// 如果有其他用户加入
		if (!otherSeatList.isEmpty()) {
			// 使用Iterator循环添加到seatList
			for (Iterator<Seat> iterator = otherSeatList.iterator(); iterator.hasNext();) {
				seatList.add(iterator.next());
			}
		}

		// 当是第二个玩家及以上时才进入循环，表示每个后来加入房间的玩家发送自己的信息到已经加入房间的玩家
		while (seatNo > 0) {// 如果该加入玩家是该房间最后一个加入的（根据userLimit判断）
			if (seatNo + 1 == userLimit) {
				String bankerSeatId = roomSeatDAO.getSeatId(roomId, "0");
				// 改变房间状态，房间已满，正在游戏中
				roomInfoDAO.changeRoomStatus(bankerSeatId, "2");
				// 通知所有玩家，指针的位置指到房主
				for (int i = 0; i < userLimit; i++) {
					OutputStream everyOutputStream = (OutputStream) MainSocket.seatMap.map
							.get(roomSeatDAO.getSeatId(roomId, i + ""));
					try {
						// 当前指针指向房主信息发送给每一个玩家
						// 因为该房间玩家以齐，所以获取房主输出流，通知房主可以发牌
						everyOutputStream.write((RespUtil.respTypeCode("001") + "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}

			// 获取其他玩家的座位id，然后获取输出流
			OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map
					.get(roomSeatDAO.getSeatId(roomId, --seatNo + ""));// 排除本玩家--seatNo
			try {
				// 将本玩家座位分别发送给其他玩家
				otherOutputStream.write((RespUtil.respTypeMessage("902", "", "seat", seat) + "\n").getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// 后面加入房间的玩家获取已经加入房间的玩家的信息
		return RespUtil.respTypeMessage("901", "", "seatList", seatList);
	}

	public void getDeal(String roomId) {
		int userLimit = Integer.parseInt(roomInfoDAO.getUserLimit(roomId));
		for (int i = 0; i < userLimit; i++) {
			OutputStream everyOutputStream = (OutputStream) MainSocket.seatMap.map
					.get(roomSeatDAO.getSeatId(roomId, i + ""));
			try {
				// 接收到房主点击发牌按钮，分别向该房间各个玩家初始化牌局,通知玩家可以押筹码
				everyOutputStream.write((RespUtil.respTypeCode("009") + "\n").getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void getBankerDealCard(String bankerSeatId) {
		String roomId = roomSeatDAO.getRoomId(bankerSeatId);
		int userLimit = Integer.parseInt((roomSeatDAO.getUserLimit(bankerSeatId)));
		List<Integer> tempList = new ArrayList<>();
		// 这些临时当作垃圾List不能同时添加到同一个Map中，不然那些Map会共用一个List
		List<Integer> tempCleanList = new ArrayList<>();
		List<Integer> tempDoubleACleanList = new ArrayList<>();
		List<Integer> tempGongCheCleanList = new ArrayList<>();
		List<Integer> tempAlreadyOpenCardCleanList = new ArrayList<>();
		List<Integer> tempFiveGongCheCleanList = new ArrayList<>();
		List<Integer> tempFiveBoomCleanList = new ArrayList<>();
		List<Integer> tempBoomCleanList = new ArrayList<>();
		List<Integer> tempNotPaiTouCleanList = new ArrayList<>();

		tempCleanList.add(1);
		tempDoubleACleanList.add(2);
		tempGongCheCleanList.add(3);
		tempAlreadyOpenCardCleanList.add(4);
		// List<Integer> goodCardList = new ArrayList<>();
		Set<Integer> set = new HashSet<>();
		Random random = new Random();
		// 记录有多少个玩家拥有公车牌型
		int gcCount = 0;
		// 该房间随机抽牌发给各个玩家，每个玩家首先获得两张牌
		while (set.size() < (userLimit * 2)) {
			set.add(random.nextInt(52));
		}

		// 将随机获得的牌存到tempList
		/*
		 * List<Integer> testList = new ArrayList<>(); testList.add(1); testList.add(3);
		 * testList.add(0); testList.add(27); testList.add(2); testList.add(48);
		 */
		tempList.addAll(set);// 测试，要改回set
		MainSocket.roomCards.put(roomId, tempCleanList);// 先保存，然后再空，为了没有多余的缓存和报错
		// 清空该房间 静态roomCards 获得的牌
		MainSocket.roomCards.get(roomId).clear();
		// 将房间号和获得的牌绑定
		MainSocket.roomCards.put(roomId, tempList);
		logger.debug(MainSocket.roomCards.get(roomId));

		// 初始化
		MainSocket.roomDealDoubleAs.put(roomId, tempDoubleACleanList);// 为了clear()时不报错
		MainSocket.roomDealDoubleAs.get(roomId).clear();// 为了保证数据不是以前的

		// 初始化
		MainSocket.roomDealGongChes.put(roomId, tempGongCheCleanList);
		MainSocket.roomDealGongChes.get(roomId).clear();

		MainSocket.roomAlreadyOpenCard.put(roomId, tempAlreadyOpenCardCleanList);
		MainSocket.roomAlreadyOpenCard.get(roomId).clear();

		MainSocket.roomFiveGongChes.put(roomId, tempFiveGongCheCleanList);
		MainSocket.roomFiveGongChes.get(roomId).clear();

		MainSocket.roomBooms.put(roomId, tempBoomCleanList);
		MainSocket.roomBooms.get(roomId).clear();

		MainSocket.roomFiveBooms.put(roomId, tempFiveBoomCleanList);
		MainSocket.roomFiveBooms.get(roomId).clear();

		MainSocket.roomNotPaiTou.put(roomId, tempNotPaiTouCleanList);
		MainSocket.roomNotPaiTou.get(roomId).clear();

		// 初始化房间发牌牌局
		for (int i = 0; i < userLimit; i++) {
			String everySeatId = roomSeatDAO.getSeatId(roomId, i + "");
			OutputStream everyOutputStream = (OutputStream) MainSocket.seatMap.map.get(everySeatId);
			OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(bankerSeatId);
			/*
			 * try { // 接收到房主点击发牌按钮，分别向该房间各个玩家初始化牌局
			 * everyOutputStream.write((RespUtil.respTypeCode("009") +
			 * "\n").getBytes("utf-8")); } catch (Exception e) { e.printStackTrace(); }
			 */

			List<Integer> cardList = new ArrayList<>();
			List<Integer> cardCleanList = new ArrayList<>();
			cardCleanList.add(i);// 随便添加一个不用的

			cardList.add(tempList.get(i));
			cardList.add(tempList.get(i + userLimit));
			MainSocket.seatCards.put(everySeatId, cardCleanList);// 先保存，然后再空，为了没有多余的缓存和报错
			// 清空该座位的牌
			MainSocket.seatCards.get(everySeatId).clear();
			// 根据seatId存放牌
			MainSocket.seatCards.put(everySeatId, cardList);

			logger.debug(MainSocket.seatCards.get(everySeatId));

			// 每个玩家将要赢得或输得的筹码，初始化每个人都是0
			MainSocket.seatChips.put(everySeatId, 0);

			// 将该房间获得双A牌型的玩家座位保存起来
			if (getACardCount(everySeatId) == 2) {
				MainSocket.roomDealDoubleAs.get(roomId).add(i);

				// 如果庄家也是双A牌型，则筹码返回0，否则返回所押筹码的两倍
				if (i != 0) {
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);
					MainSocket.seatChips.put(everySeatId, MainSocket.roomDealDoubleAs.get(roomId).contains(0) ? 0
							: MainSocket.seatEscrows.get(everySeatId) * 2);
				}
				// 将该房间获得A+J或A+Q或A+K牌型的玩家座位保存起来
			} else if (getACardCount(everySeatId) == 1 && getDealCardValue(everySeatId) > 11) {
				MainSocket.roomDealGongChes.get(roomId).add(i);

				if (i != 0) {
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);
					MainSocket.seatChips.put(everySeatId, MainSocket.roomDealDoubleAs.get(roomId).contains(0)// 房主的牌型是双A
							? (-MainSocket.seatEscrows.get(everySeatId) * 2)
							: (MainSocket.roomDealGongChes.get(roomId).contains(0)
									? (getDealCardValue(bankerSeatId) > getDealCardValue(everySeatId))
											? (-MainSocket.seatEscrows.get(everySeatId))
											: (getDealCardValue(bankerSeatId) < getDealCardValue(everySeatId))
													? MainSocket.seatEscrows.get(everySeatId)
													: 0
									: MainSocket.seatEscrows.get(everySeatId)));
				}
			} else {
				if (MainSocket.roomDealDoubleAs.get(roomId).contains(0)) {
					MainSocket.seatChips.put(everySeatId, (-MainSocket.seatEscrows.get(everySeatId) * 2));
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);
				} else if (MainSocket.roomDealGongChes.get(roomId).contains(0)) {
					MainSocket.seatChips.put(everySeatId, (-MainSocket.seatEscrows.get(everySeatId)));
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);
				}
			}
			MainSocket.seatChips.put(bankerSeatId, -MainSocket.seatChips.get(everySeatId));
			logger.debug(MainSocket.seatChips.get(everySeatId));
			logger.debug(MainSocket.seatChips.get(bankerSeatId));
			logger.debug(MainSocket.roomAlreadyOpenCard.get(roomId));

			/*
			 * if (MainSocket.roomDealDoubleAs.get(roomId).contains(i) ||
			 * MainSocket.roomDealGongChes.get(roomId).contains(i)) {
			 * MainSocket.seatChips.put(everySeatId, // 当前玩家得到两张A
			 * MainSocket.roomDealDoubleAs.get(roomId).contains(i) //
			 * 庄家是否获得两张A，庄家也获得两张A则返回0，否则返回押的筹码的两倍 ?
			 * (MainSocket.roomDealDoubleAs.get(roomId).contains(0) ? 0 :
			 * MainSocket.seatEscrows.get(everySeatId) * 2) // 当前玩家牌型的值大于庄家牌型的值 :
			 * ((getDealCardValue(everySeatId) > getDealCardValue(bankerSeatId)) //
			 * 当前玩家牌型的值大于庄家牌型的值为真，返回所押的筹码 ? MainSocket.seatEscrows.get(everySeatId) //
			 * 当前玩家牌型的值大于庄家牌型的值为真，返回减去所押的筹码；否则就是两者牌型的值相等，返回0 :
			 * (getDealCardValue(everySeatId) < getDealCardValue(bankerSeatId)) ?
			 * -MainSocket.seatEscrows.get(everySeatId) : 0));
			 * 
			 * }
			 */
			try {
				// 接收到房主点击发牌按钮，分别向该房间各个玩家发送他们随机获取的牌002
				everyOutputStream.write(
						(RespUtil.respTypeMessage("002", "", "dealCards", MainSocket.seatCards.get(everySeatId)) + "\n")
								.getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}

			try {
				// 玩家结算的筹码发送给玩家
				everyOutputStream.write(
						(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(everySeatId)) + "\n")
								.getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				// 庄家结算的筹码发送给玩家
				bankerOutputStream.write(
						(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(bankerSeatId)) + "\n")
								.getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		// 得到该房间内每一个玩家的输出流
		for (int i = 0; i < userLimit; i++) {
			String everySeatId = roomSeatDAO.getSeatId(roomId, i + "");

			// 表示两张牌中，其中有一张是A：A的值可以变换，A=1/11，
			/**
			 * 报错： Exception in thread "Thread-12" java.lang.NullPointerException at
			 * com.atu.poker.service.RoomSeatService.getCard(RoomSeatService.java:119) at
			 * com.atu.poker.thread.SocketThread.deal(SocketThread.java:146) at
			 * com.atu.poker.thread.SocketThread.selectReqType(SocketThread.java:115) at
			 * com.atu.poker.thread.SocketThread.run(SocketThread.java:75) at
			 * java.lang.Thread.run(Thread.java:745)
			 * 改变set.add(random.nextInt(54));为set.add(random.nextInt(52));
			 */

			// 两张都是A，双A,可以直接翻牌拿钱
			// A最低带一个J以上，可以直接翻牌拿钱。注意：A+10只是等于21点，不能直接翻牌拿钱
			// if (one+two==2) {
			//
			// }else if (one+two>11) {
			//
			// }
			// 这是牌型是公车以上牌型
			if (MainSocket.roomDealDoubleAs.get(roomId).contains(i)
					|| MainSocket.roomDealGongChes.get(roomId).contains(i)) {
				// goodCardList.add(i);
				gcCount++;

				// 房主开公车，或者除了房主之外所有玩家开公车
				if (i == 0 || (gcCount == userLimit - 1 && i != 0)) {
					openCard("", roomId);
					break;
				}

				for (int j = 0; j < userLimit; j++) {
					if (j != i) {
						OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map
								.get(roomSeatDAO.getSeatId(roomId, j + ""));
						try {
							otherOutputStream
									// 发送座位号给其他玩家，i是当前玩家座位号003
									.write((RespUtil.respTypeMessage("003", i + "", "dealCards",
											MainSocket.seatCards.get(everySeatId)) + "\n")// cardList->MainSocket.seatCards.get(everySeatId)
													.getBytes("utf-8"));
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					nextPlayerPointer(bankerSeatId);
				}

				// 以下获得的牌型，不能直接翻牌
			} else {
				for (int j = 0; j < userLimit; j++) {
					if (j != i) {
						OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map
								.get(roomSeatDAO.getSeatId(roomId, j + ""));
						try {
							// 发送座位号给其他玩家，i是当前玩家座位号004
							otherOutputStream
									.write((RespUtil.respTypeMessage("004", "", "seatNo", i) + "\n").getBytes("utf-8"));
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
				nextPlayerPointer(bankerSeatId);
			}
		}
		/*
		 * if (!MainSocket.roomDealDoubleAs.get(roomId).contains(0) ||
		 * !MainSocket.roomDealGongChes.get(roomId).contains(0)) {
		 * nextPlayerPointer(bankerSeatId); }
		 */

	}

	public void sendSeatEscrow(String seatId, String escrow) {
		MainSocket.seatEscrows.put(seatId, Integer.parseInt(escrow));
		logger.debug(MainSocket.seatEscrows);
		String roomId = roomSeatDAO.getRoomId(seatId);
		String seatNo = roomSeatDAO.getSeatNo(seatId);
		int userLimit = Integer.parseInt(roomSeatDAO.getUserLimit(seatId));

		for (int i = 0; i < userLimit; i++) {
			String everySeatId = roomSeatDAO.getSeatId(roomId, i + "");
			OutputStream everyOutputStream = (OutputStream) MainSocket.seatMap.map.get(everySeatId);
			try {
				everyOutputStream
						// 发送该座位玩家押的筹码010
						.write((RespUtil.respTypeMessage("010", seatNo, "escrow", MainSocket.seatEscrows.get(seatId))
								+ "\n").getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void saveSeatChip(String seatId, String chip) {

	}

	public void sendCard(String seatId) {
		String roomId = roomSeatDAO.getRoomId(seatId);
		int seatNo = Integer.parseInt(roomSeatDAO.getSeatNo(seatId));
		int userLimit = Integer.parseInt(roomSeatDAO.getUserLimit(seatId));

		// 发一张牌给该座位玩家
		MainSocket.seatCards.get(seatId).add(getRandomCard(roomId));
		logger.debug(MainSocket.seatCards.get(seatId));

		// 五张牌的公车，摸到了五张牌还没有大于21点
		if (MainSocket.seatCards.get(seatId).size() == 5 && getFirstSizeCardValue(seatId) <= 21) {
			MainSocket.roomFiveGongChes.get(roomId).add(seatNo);
			if (seatNo == 0) {// 庄家是最后摸牌的，当庄家摸到了五张牌且大小小于21点时，
				OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);

				for (int i = 1; i < userLimit; i++) {
					String otherSeatId = roomSeatDAO.getSeatId(roomId, i + "");
					OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(otherSeatId);
					// 庄家摸了五张牌还没有爆（未超过21点），其他玩家就要返回减去押的筹码的两倍
					MainSocket.seatChips.put(otherSeatId, -MainSocket.seatEscrows.get(otherSeatId) * 2);
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);

					MainSocket.seatChips.put(seatId, -MainSocket.seatChips.get(otherSeatId));
					logger.debug(MainSocket.seatChips.get(otherSeatId));
					logger.debug(MainSocket.seatChips.get(seatId));

					try {
						// 玩家结算的筹码发送给玩家
						otherOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(otherSeatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
					try {
						// 庄家结算的筹码发送给玩家
						bankerOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} else {
				String bankerSeatId = roomSeatDAO.getSeatId(roomId, 0 + "");
				OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(bankerSeatId);
				OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);
				// 如果不是庄家（其他玩家）摸到五张牌还未大于21点，则返回所押筹码的两倍
				MainSocket.seatChips.put(seatId, MainSocket.seatEscrows.get(seatId) * 2);
				MainSocket.roomAlreadyOpenCard.get(roomId).add(seatNo);

				MainSocket.seatChips.put(bankerSeatId, -MainSocket.seatChips.get(seatId));
				logger.debug(MainSocket.seatChips.get(seatId));
				logger.debug(MainSocket.seatChips.get(bankerSeatId));

				try {
					// 玩家结算的筹码发送给玩家
					otherOutputStream.write(
							(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId)) + "\n")
									.getBytes("utf-8"));
				} catch (Exception e) {
					e.printStackTrace();
				}
				try {
					// 庄家结算的筹码发送给玩家
					bankerOutputStream.write(
							(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(bankerSeatId))
									+ "\n").getBytes("utf-8"));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		// 摸到了五张牌大于21点,这个刚好和上一个相反
		if (MainSocket.seatCards.get(seatId).size() == 5 && getFirstSizeCardValue(seatId) > 21) {
			MainSocket.roomFiveBooms.get(roomId).add(seatNo);
			if (seatNo == 0) {
				OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);
				for (int i = 1; i < userLimit; i++) {
					String otherSeatId = roomSeatDAO.getSeatId(roomId, i + "");
					OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(otherSeatId);
					// 庄家摸了五张牌爆了，其他玩家就返回所押筹码的两倍
					MainSocket.seatChips.put(otherSeatId, MainSocket.seatEscrows.get(otherSeatId) * 2);
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);

					MainSocket.seatChips.put(seatId, -MainSocket.seatChips.get(otherSeatId));
					logger.debug(MainSocket.seatChips.get(otherSeatId));
					logger.debug(MainSocket.seatChips.get(seatId));

					try {
						// 玩家结算的筹码发送给玩家
						otherOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(otherSeatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
					try {
						// 庄家结算的筹码发送给玩家
						bankerOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} else {
				String bankerSeatId = roomSeatDAO.getSeatId(roomId, 0 + "");
				OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(bankerSeatId);
				OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);
				// 如果不是庄家（其他玩家）摸到五张牌大于21点，则返回减去所押筹码的两倍
				MainSocket.seatChips.put(seatId, -MainSocket.seatEscrows.get(seatId) * 2);
				MainSocket.roomAlreadyOpenCard.get(roomId).add(seatNo);

				MainSocket.seatChips.put(bankerSeatId, -MainSocket.seatChips.get(seatId));
				logger.debug(MainSocket.seatChips.get(seatId));
				logger.debug(MainSocket.seatChips.get(bankerSeatId));

				try {
					// 玩家结算的筹码发送给玩家
					otherOutputStream.write(
							(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId)) + "\n")
									.getBytes("utf-8"));
				} catch (Exception e) {
					e.printStackTrace();
				}
				try {
					// 庄家结算的筹码发送给玩家
					bankerOutputStream.write(
							(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(bankerSeatId))
									+ "\n").getBytes("utf-8"));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		// 摸到的牌小于五张且大于21点
		if (MainSocket.seatCards.get(seatId).size() < 5 && getFirstSizeCardValue(seatId) > 21) {
			MainSocket.roomBooms.get(roomId).add(seatNo);
			if (seatNo == 0) {
				OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);
				for (int i = 1; i < userLimit; i++) {
					String otherSeatId = roomSeatDAO.getSeatId(roomId, i + "");
					OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(otherSeatId);
					// 如果庄家摸到小于五张牌爆了，其他玩家返回所押筹码
					MainSocket.seatChips.put(otherSeatId, MainSocket.seatEscrows.get(otherSeatId));
					MainSocket.roomAlreadyOpenCard.get(roomId).add(i);

					MainSocket.seatChips.put(seatId, -MainSocket.seatChips.get(otherSeatId));
					logger.debug(MainSocket.seatChips.get(otherSeatId));
					logger.debug(MainSocket.seatChips.get(seatId));

					try {
						// 玩家结算的筹码发送给玩家
						otherOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(otherSeatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
					try {
						// 庄家结算的筹码发送给玩家
						bankerOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} else {
				String bankerSeatId = roomSeatDAO.getSeatId(roomId, 0 + "");
				OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(bankerSeatId);
				OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);
				// 如果其他玩家摸到小于五张牌爆了，其他玩家返回减去所押筹码
				MainSocket.seatChips.put(seatId, -MainSocket.seatEscrows.get(seatId));
				MainSocket.roomAlreadyOpenCard.get(roomId).add(seatNo);

				MainSocket.seatChips.put(bankerSeatId, -MainSocket.seatChips.get(seatId));
				logger.debug(MainSocket.seatChips.get(seatId));
				logger.debug(MainSocket.seatChips.get(bankerSeatId));

				try {
					// 玩家结算的筹码发送给玩家
					otherOutputStream.write(
							(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId)) + "\n")
									.getBytes("utf-8"));
				} catch (Exception e) {
					e.printStackTrace();
				}
				try {
					// 庄家结算的筹码发送给玩家
					bankerOutputStream.write(
							(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(bankerSeatId))
									+ "\n").getBytes("utf-8"));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		// 如果玩家手中的牌等于五张并且五张牌大小加起来小于21
		/*
		 * if ((MainSocket.seatCards.get(seatId).size() == 5 &&
		 * (getSecondSizeCardValue(seatId) - (getACardCount(seatId) * 10)) <= 21) //
		 * 得到的牌型大于21点 || ((getSecondSizeCardValue(seatId) - (getACardCount(seatId) *
		 * 10)) > 21 && getSecondSizeCardValue(seatId) > 21)) {
		 */
		if (MainSocket.roomFiveGongChes.get(roomId).contains(seatNo)
				|| MainSocket.roomFiveBooms.get(roomId).contains(seatNo)
				|| MainSocket.roomBooms.get(roomId).contains(seatNo)) {

			if (seatNo == 0) {
				openCard("", roomId);
			} else {
				for (int i = 0; i < userLimit; i++) {
					OutputStream everyOutputStream = (OutputStream) MainSocket.seatMap.map
							.get(roomSeatDAO.getSeatId(roomId, i + ""));
					try {
						// 不能继续摸牌006
						everyOutputStream.write((RespUtil.respTypeMessage("006", seatNo + "", "cardList",
								MainSocket.seatCards.get(seatId)) + "\n").getBytes("utf-8"));
						logger.debug(MainSocket.seatCards.get(seatId));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				nextPlayerPointer(seatId);
			}

		} else {
			for (int i = 0; i < userLimit; i++) {
				if (i != seatNo) {
					OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map
							.get(roomSeatDAO.getSeatId(roomId, i + ""));
					try {
						// 可以继续摸牌007
						otherOutputStream
								.write((RespUtil.respTypeMessage("007", MainSocket.seatCards.get(seatId).size() + "",
										"seatNo", seatNo) + "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				} else {
					OutputStream selfOutputStream = (OutputStream) MainSocket.seatMap.map
							.get(roomSeatDAO.getSeatId(roomId, seatNo + ""));
					try {
						// 将开牌玩家的牌发送给自己008
						selfOutputStream.write(
								(RespUtil.respTypeMessage("008", MainSocket.seatCards.get(seatId).size() + "", "card",
										MainSocket.seatCards.get(seatId)
												.get(MainSocket.seatCards.get(seatId).size() - 1))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	public void nextPlayerPointer(String seatId) {
		String roomId = roomSeatDAO.getRoomId(seatId);
		int seatNo = Integer.parseInt(roomSeatDAO.getSeatNo(seatId));
		int userLimit = Integer.parseInt(roomSeatDAO.getUserLimit(seatId));
		/*
		 * if ((getACardCount(seatId) == 1 && getSecondSizeCardValue(seatId) >= 16 &&
		 * getSecondSizeCardValue(seatId) <= 21) || getFirstSizeCardValue(seatId) >= 16)
		 * {
		 */
		seatNo++;
		// 当该玩家牌型是两张牌时且双A或A+J或A+Q或A+K
		while (MainSocket.roomDealDoubleAs.get(roomId).contains(seatNo)
				|| MainSocket.roomDealGongChes.get(roomId).contains(seatNo)) {
			seatNo++;
			// 如果i==（玩家总数-1）座位号为最后一位玩家，则i==0
			// i = i == userLimit ? 0 : i;// 这里不需要userLimit-1，因为循环第一步已经i++了，所以userLimit刚好正确
			seatNo = seatNo == userLimit ? 0 : seatNo;
		}
		seatNo = seatNo == userLimit ? 0 : seatNo;
		for (int i = 0; i < userLimit; i++) {
			// 获取每一个玩家的seatId
			String everySeatId = roomSeatDAO.getSeatId(roomId, i + "");
			OutputStream everyOutputStream = (OutputStream) MainSocket.seatMap.map.get(everySeatId);
			try {
				everyOutputStream
						// 发送指针座位号给每一个玩家，i是指针指向的座位号009,先测试005
						.write((RespUtil.respTypeMessage("005", "", "pointerSeatNo", seatNo + "") + "\n")
								.getBytes("utf-8"));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		// }
	}

	/**
	 * 封装静态的方法，该房间每位玩家每次只能获得的一张不重复的牌牌
	 * 
	 * @param roomId
	 * @return
	 */
	public static int getRandomCard(String roomId) {
		Random random = new Random();
		for (int i = 1; i < 2; i++) {
			int j = random.nextInt(52);
			if (MainSocket.roomCards.get(roomId).contains(j)) {
				i--;
			} else {
				MainSocket.roomCards.get(roomId).add(j);
			}
		}
		return MainSocket.roomCards.get(roomId).get(MainSocket.roomCards.get(roomId).size() - 1);
	}

	/**
	 * 抓牌以后两张牌的情况时牌的大小 封装手中所有牌的joker大小，大于21点就爆, A的大小转换成11点
	 * 
	 * @param seatId
	 * @return
	 */
	public static int getSecondSizeCardValue(String seatId) {
		int cardValue = 0;
		for (int i = 0; i < MainSocket.seatCards.get(seatId).size(); i++) {
			cardValue += CardMap.SIZECARDMAP.map.get(MainSocket.seatCards.get(seatId).get(i).toString()) == 1
					? CardMap.SIZECARDMAP.map.get(MainSocket.seatCards.get(seatId).get(i).toString()) + 10
					: CardMap.SIZECARDMAP.map.get(MainSocket.seatCards.get(seatId).get(i).toString());
		}
		cardValue += getACardCount(seatId) > 1 ? (-(getACardCount(seatId) - 1) * 10) : 0;
		return cardValue > 21 ? cardValue - 10 : cardValue;
	}

	/**
	 * 抓牌以后两张牌的情况时牌的大小 封装手中所有牌的joker大小，大于21点就爆, A的大小是1的情况
	 * 
	 * @param seatId
	 * @return
	 */
	public static int getFirstSizeCardValue(String seatId) {
		int cardValue = 0;
		for (int i = 0; i < MainSocket.seatCards.get(seatId).size(); i++) {
			cardValue += CardMap.SIZECARDMAP.map.get(MainSocket.seatCards.get(seatId).get(i).toString());
		}

		return cardValue;
	}

	/**
	 * 开局时每个玩家只有两张牌时的大小,A 的大小是1，两张牌有A时的情况
	 * 
	 * @param seatId
	 * @return
	 */
	public static int getDealCardValue(String seatId) {
		int cardValue = 0;
		for (int i = 0; i < MainSocket.seatCards.get(seatId).size(); i++) {
			cardValue += CardMap.DEALCARDMAP.map.get(MainSocket.seatCards.get(seatId).get(i).toString());
		}

		return cardValue;
	}

	/**
	 * 获得玩家手中A的数量
	 * 
	 * @param seatId
	 * @return
	 */
	public static int getACardCount(String seatId) {
		int count = 0;
		for (int i = 0; i < MainSocket.seatCards.get(seatId).size(); i++) {
			if (CardMap.DEALCARDMAP.map.get(MainSocket.seatCards.get(seatId).get(i).toString()) == 1) {
				count++;
			}
		}
		return count;
	}

	/**
	 * 只有房主才能进行开牌操作
	 * 
	 * @param seatNo
	 * @param roomId
	 */
	public void openCard(String seatNo, String roomId) {
		int userLimit = Integer.parseInt(roomInfoDAO.getUserLimit(roomId));

		String bankerSeatId = roomSeatDAO.getSeatId(roomId, 0 + "");

		OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(bankerSeatId);
		if ((getACardCount(bankerSeatId) > 0 && getSecondSizeCardValue(bankerSeatId) >= 16
				&& getSecondSizeCardValue(bankerSeatId) <= 21) || getFirstSizeCardValue(bankerSeatId) >= 16
				|| getACardCount(bankerSeatId) == 2
				|| (getACardCount(bankerSeatId) == 1 && getDealCardValue(bankerSeatId) > 11)) {
			if ("".equals(seatNo)) {

				// OutputStream bankerOutputStream = (OutputStream)
				// MainSocket.seatMap.map.get(bankerSeatId);
				for (int i = 0; i < userLimit; i++) {
					if (!MainSocket.roomAlreadyOpenCard.get(roomId).contains(i) && i != 0) {
						String otherSeatId = roomSeatDAO.getSeatId(roomId, i + "");
						OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(otherSeatId);
						MainSocket.seatChips.put(otherSeatId,
								getSecondSizeCardValue(otherSeatId) > getSecondSizeCardValue(bankerSeatId)
										? MainSocket.seatEscrows.get(otherSeatId)
										: getSecondSizeCardValue(otherSeatId) < getSecondSizeCardValue(bankerSeatId)
												? -MainSocket.seatEscrows.get(otherSeatId)
												: 0);
						MainSocket.seatChips.put(bankerSeatId, -MainSocket.seatChips.get(otherSeatId));
						logger.debug(MainSocket.seatChips.get(otherSeatId));
						logger.debug(MainSocket.seatChips.get(bankerSeatId));

						try {
							// 玩家结算的筹码发送给玩家
							otherOutputStream.write((RespUtil.respTypeMessage("012", "", "userChip",
									MainSocket.seatChips.get(otherSeatId)) + "\n").getBytes("utf-8"));
						} catch (Exception e) {
							e.printStackTrace();
						}
						try {
							// 庄家结算的筹码发送给玩家
							bankerOutputStream.write((RespUtil.respTypeMessage("012", "", "userChip",
									MainSocket.seatChips.get(bankerSeatId)) + "\n").getBytes("utf-8"));
						} catch (Exception e) {
							e.printStackTrace();
						}
					}

					// 循环得到所有玩家的牌型
					List<Integer> everyPlayerCardList = MainSocket.seatCards.get(roomSeatDAO.getSeatId(roomId, i + ""));
					for (int j = 0; j < userLimit; j++) {
						// 循环得到所有玩家的流
						// 将自己的牌发送给每一个不是自己的玩家
						OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map
								.get(roomSeatDAO.getSeatId(roomId, j + ""));
						try {
							otherOutputStream
									// 发送座位号给其他玩家，i是当前玩家座位号006
									.write((RespUtil.respTypeMessage("006", i + "", "cardList", everyPlayerCardList)
											+ "\n").getBytes("utf-8"));
							logger.debug(everyPlayerCardList);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			} else {
				String seatId = roomSeatDAO.getSeatId(roomId, seatNo);
				OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);

				if (!MainSocket.roomAlreadyOpenCard.get(roomId).contains(Integer.parseInt(seatNo))) {
					MainSocket.seatChips.put(seatId,
							getSecondSizeCardValue(seatId) > getSecondSizeCardValue(bankerSeatId)
									? MainSocket.seatEscrows.get(seatId)
									: getSecondSizeCardValue(seatId) < getSecondSizeCardValue(bankerSeatId)
											? -MainSocket.seatEscrows.get(seatId)
											: 0);
					MainSocket.seatChips.put(bankerSeatId, -MainSocket.seatChips.get(seatId));
					logger.debug(MainSocket.seatChips.get(seatId));
					logger.debug(MainSocket.seatChips.get(bankerSeatId));

					try {
						// 玩家结算的筹码发送给玩家
						otherOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(seatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
					try {
						// 庄家结算的筹码发送给玩家
						bankerOutputStream.write(
								(RespUtil.respTypeMessage("012", "", "userChip", MainSocket.seatChips.get(bankerSeatId))
										+ "\n").getBytes("utf-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

				// 房主所要开牌的玩家的牌型
				List<Integer> thisPlayerCardList = MainSocket.seatCards.get(seatId);
				// 房主的牌型
				List<Integer> bankerPlayerCardList = MainSocket.seatCards.get(bankerSeatId);

				try {
					// 将当前房主选择开牌的玩家的牌型发送给房主
					bankerOutputStream
							.write((RespUtil.respTypeMessage("006", seatNo + "", "cardList", thisPlayerCardList) + "\n")
									.getBytes("utf-8"));
					logger.debug(thisPlayerCardList);
				} catch (Exception e1) {
					e1.printStackTrace();
				}

				OutputStream thisOutputStream = (OutputStream) MainSocket.seatMap.map.get(seatId);
				try {
					// 将房主的牌型只发送发送给该玩家
					thisOutputStream
							.write((RespUtil.respTypeMessage("006", 0 + "", "cardList", bankerPlayerCardList) + "\n")
									.getBytes("utf-8"));
					logger.debug(bankerPlayerCardList);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void getSettlementChip(String roomId, String bankerChip) {
		int userLimit = Integer.parseInt(roomInfoDAO.getUserLimit(roomId));

		for (int i = 1; i < userLimit; i++) {
			// 通知闲家庄家结算筹码
			OutputStream otherOutputStream = (OutputStream) MainSocket.seatMap.map
					.get(roomSeatDAO.getSeatId(roomId, i + ""));
			try {
				otherOutputStream
						// 通知闲家结算筹码，i是当前玩家座位号604
						.write((RespUtil.respTypeMessage("013", "", "bankerChip", bankerChip) + "\n")
								.getBytes("utf-8"));
				logger.debug(bankerChip);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void bankerSettlement(String seatId, String chip) {
		String roomId = roomSeatDAO.getRoomId(seatId);
		int seatNo = Integer.parseInt(roomSeatDAO.getSeatNo(seatId));

		String bankerSeatId = roomSeatDAO.getSeatId(roomId, 0 + "");

		OutputStream bankerOutputStream = (OutputStream) MainSocket.seatMap.map.get(bankerSeatId);

		try {
			bankerOutputStream
					// 通知庄家结算筹码，i是当前玩家座位号014
					.write((RespUtil.respTypeMessage("014", seatNo + "", "playerChip", chip) + "\n").getBytes("utf-8"));
			logger.debug(chip);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
